package com.knowvoyage.knowvoyageserver.service.Impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.knowvoyage.knowvoyageserver.mapper.DialogMapper;
import com.knowvoyage.knowvoyageserver.mapper.FavoriteMapper;
import com.knowvoyage.knowvoyageserver.mapper.MessageMapper;
import com.knowvoyage.knowvoyageserver.pojo.dto.FavoriteDTO;
import com.knowvoyage.knowvoyageserver.pojo.entity.Dialog;
import com.knowvoyage.knowvoyageserver.pojo.entity.Favorite;
import com.knowvoyage.knowvoyageserver.pojo.entity.Message;
import com.knowvoyage.knowvoyageserver.pojo.vo.FavoriteVO;
import com.knowvoyage.knowvoyageserver.pojo.vo.Result;
import com.knowvoyage.knowvoyageserver.service.FavoriteService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class FavoriteServiceImpl implements FavoriteService {
    private final FavoriteMapper favoriteMapper;
    private final MessageMapper  messageMapper;
    private final DialogMapper  dialogMapper;

    private final RedisTemplate<String, Object> redisTemplate;  // 注入 RedisTemplate

    // 缓存键前缀
    private static final String FAVORITE_CACHE_PREFIX = "favorite:user:";

    // 序列化工具
    private static final ObjectMapper objectMapper = new ObjectMapper();
    /**
     * 插入收藏记录
     * @param favorite 收藏记录
     * @return 插入结果
     */
    @Override
    public Result<Boolean> insert(Favorite favorite) {
        //判断messageId对应dialogId是否属于userId对应用户。
//        Message message = messageMapper.selectById(favorite.getMessageId());
//        Dialog dialog = dialogMapper.selectById(message.getDialogId());
//        if(!dialog.getUserId().equals(favorite.getUserId())){
//            log.info("该消息不在该用户dialogId之下");
//            return Result.error(400, "该消息不在该用户dialogId之下");
//        }
        //是否已经收藏
        if (favoriteMapper.selectByMessageAndUser(favorite.getMessageId(), favorite.getUserId()) != null) {
            log.info("该消息已收藏");
            return Result.error(400, "该消息已收藏");
        }
        favoriteMapper.insert(favorite);
        log.info("favoriteId：{}", favorite.getFavoriteId());

        String pattern = FAVORITE_CACHE_PREFIX + favorite.getUserId() + ":*";
        Set<String> keys = redisTemplate.keys(pattern);
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }
        return Result.success(true);
    }

    /**
     * 删除收藏记录
     * @param favoriteId 收藏记录ID
     * @return 删除结果
     */
    @Override
    public Result<Boolean> delete(Long favoriteId, Authentication authentication) {
        // 查询收藏记录
        Favorite favorite = favoriteMapper.selectById(favoriteId);
        if (favorite == null) {
            return Result.error(404, "收藏记录不存在");
        }

        Long ownerId = favorite.getUserId();
        Long currentUserId = (Long) authentication.getPrincipal();

        // 校验是否是当前用户自己的收藏
        if (!ownerId.equals(currentUserId)) {
            return Result.error(403, "无权删除他人收藏记录");
        }

        // 删除数据库记录
        favoriteMapper.delete(favoriteId);

        // 删除缓存
        String pattern = FAVORITE_CACHE_PREFIX + ownerId + ":*";
        Set<String> keys = redisTemplate.keys(pattern);
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }

        return Result.success(true);
    }


    /**
     * 根据收藏记录ID查询收藏记录
     * @param favoriteId 收藏记录ID
     * @return 收藏记录
     */
    @Override
    public Result<FavoriteVO> selectById(Long favoriteId) {
        Favorite favorite = favoriteMapper.selectById(favoriteId);
        if (favorite == null) {
            return Result.error(404,"收藏记录不存在");
        }

        // 2. 获取关联消息内容
        Message message = messageMapper.selectById(favorite.getMessageId());
        if (message == null) {
            return Result.error(404,"关联消息已删除");
        }

        // 3. 转换为 VO
        FavoriteVO vo = new FavoriteVO();
        BeanUtils.copyProperties(favorite, vo);  // 复制基础字段
        vo.setAsk(message.getAsk());
        vo.setReply(message.getReply());

        return Result.success(vo);
    }

    /**
     * 根据用户ID查询该用户所有收藏记录
     * @param userId 用户ID
     * @param pageNum 页码
     * @param pageSize 每页数量
     * @return 收藏记录列表
     */
    @Override
    public PageInfo<FavoriteVO> selectAllByUser(Long userId, int pageNum, int pageSize) {

        String cacheKey = String.format("%s%d:page:%d:size:%d", FAVORITE_CACHE_PREFIX, userId, pageNum, pageSize);
        String cachedResult = (String) redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            try {
                return objectMapper.readValue(cachedResult, new TypeReference<PageInfo<FavoriteVO>>() {});
            } catch (JsonProcessingException e) {
                log.error("反序列化缓存失败: {}", e.getMessage());
            }
        }
        log.info("缓存未命中，开始查询数据库...");
        PageHelper.startPage(pageNum, pageSize);
        List<Favorite> favorites = favoriteMapper.selectByUserId(userId);

        // 提取 messageIds 并去重
        List<Long> messageIds = favorites.stream()
                .map(Favorite::getMessageId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        if (messageIds.isEmpty()) {
            return new PageInfo<>(Collections.emptyList());
        }

        // 确保 selectByMessageIds 返回 List<Message>
        List<Message> messages = messageMapper.selectByMessageIds(messageIds);

        // 显式构建 Map<Long, Message>
        Map<Long, Message> messageMap = messages.stream()
                .collect(Collectors.toMap(
                        Message::getMessageId,
                        Function.identity(),
                        (oldVal, newVal) -> oldVal  // 处理重复键
                ));

        // 转换为 VO
        List<FavoriteVO> favoriteVOs = favorites.stream()
                .map(favorite -> {
                    FavoriteVO vo = new FavoriteVO();
                    vo.setFavoriteId(favorite.getFavoriteId());
                    vo.setMessageId(favorite.getMessageId());
                    vo.setUserId(favorite.getUserId());

                    Message message = messageMap.get(favorite.getMessageId());
                    if (message != null) {
                        vo.setAsk(message.getAsk());
                        vo.setReply(message.getReply());
                    }
                    return vo;
                })
                .collect(Collectors.toList());

        PageInfo<FavoriteVO> pageInfo = new PageInfo<>(favoriteVOs);

        // 将结果序列化并存入 Redis
        try {
            String json = objectMapper.writeValueAsString(pageInfo);
            redisTemplate.opsForValue().set(cacheKey, json, 30, TimeUnit.MINUTES);  // 设置 30 分钟过期
        } catch (JsonProcessingException e) {
            log.error("序列化缓存失败: {}", e.getMessage());
        }
        log.info("缓存已更新{}",pageInfo);

        return pageInfo;
    }

    /**
     * 根据消息ID和用户ID查询收藏记录
     * @param messageId 消息ID
     * @param userId 用户ID
     * @return 收藏记录
     */
    @Override
    public Result<Favorite> selectByMessageAndUser(Long messageId, Long userId) {
        Favorite favorite = favoriteMapper.selectByMessageAndUser(messageId, userId);
        if (favorite == null) {
            return Result.error(404, "未找到该用户对指定消息的收藏记录");
        }
        return Result.success(favorite);
    }

    /**
     * 查询所有收藏记录
     * @return 收藏记录列表
     */
    @Override
    public Result<List<Favorite>> selectAll() {
        List<Favorite> favorites = favoriteMapper.selectAll();
        if (favorites == null || favorites.isEmpty()) {
            return Result.success(Collections.emptyList()); // 返回空列表而非null
        }
        return Result.success(favorites);
    }
    @Override
    public Result<Boolean> update(Favorite favorite) {
        // 1. 校验收藏记录是否存在
        Favorite existing = favoriteMapper.selectById(favorite.getFavoriteId());
        if (existing == null) {
            return Result.error(404, "收藏记录不存在");
        }

        // 2. 校验用户权限（确保用户只能修改自己的收藏）
        if (!existing.getUserId().equals(favorite.getUserId())) {
            return Result.error(403, "无权修改其他用户的收藏记录");
        }

        // 3. 执行更新
        favoriteMapper.update(favorite); // 假设Mapper已添加update方法

        // 4. 清除相关缓存
        String pattern = FAVORITE_CACHE_PREFIX + favorite.getUserId() + ":*";
        Set<String> keys = redisTemplate.keys(pattern);
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }

        return Result.success(true);
    }
    /**
     * 批量删除收藏记录
     * @param favoriteIds 收藏记录ID列表
     * @return 删除结果
     */
    @Override
    public Result<Boolean> batchDelete(Long currentUserId, List<Long> favoriteIds) {
        if (favoriteIds == null || favoriteIds.isEmpty()) {
            return Result.error(400, "参数 favoriteIds 不能为空");
        }

        // 从数据库查出所有这些Favorite
        List<Favorite> favorites = favoriteMapper.selectByIds(favoriteIds);
        if (favorites.isEmpty()) {
            return Result.error(404, "没有找到对应的收藏记录");
        }


        // 校验：每一条记录的 userId 都必须等于 currentUserId
        boolean allOk = favorites.stream()
                .allMatch(fav -> fav.getUserId().equals(currentUserId));
        if (!allOk) {
            return Result.error(403, "包含非当前用户的收藏，禁止删除");
        }

        // 真正删除
        favoriteMapper.batchDelete(favoriteIds);

        // 清理缓存，仅针对当前 userId
        String pattern = FAVORITE_CACHE_PREFIX + currentUserId + ":*";
        Set<String> keys = redisTemplate.keys(pattern);
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }

        return Result.success(true);
    }
    /**
     * 统计某个用户收藏数量
     * @param userId 用户ID
     * @return 收藏数量
     */
    @Override
    public Result<Integer> countByUserId(Long userId) {
        int count = favoriteMapper.countByUserId(userId);
        return Result.success(count);
    }
    /**
     * 统计某消息被收藏次数
     * @param messageId 消息ID
     * @return 收藏次数
     */
    @Override
    public Result<Integer> countByMessageId(Long messageId) {
        int count = favoriteMapper.countByMessageId(messageId);
        log.info("消息ID：{}，被收藏次数：{}", messageId, count);
        return Result.success(count);
    }

    /**
     * 批量插入收藏记录
     * @param favoriteDTOs 收藏记录DTO列表
     * @return 插入结果
     */
    @Override
    public Result<Boolean> batchInsert(List<FavoriteDTO> favoriteDTOs) {
        if (favoriteDTOs == null || favoriteDTOs.isEmpty()) {
            return Result.error(400, "参数不能为空");
        }

        // DTO -> Entity 转换
        List<Favorite> allFavorites = favoriteDTOs.stream().map(dto -> {
            Favorite fav = new Favorite();
            BeanUtils.copyProperties(dto, fav);
            return fav;
        }).collect(Collectors.toList());

        // 去重：排除数据库中已存在的收藏记录
        List<Favorite> insertableFavorites = allFavorites.stream()
                .filter(fav -> favoriteMapper.selectByMessageAndUser(fav.getMessageId(), fav.getUserId()) == null)
                .collect(Collectors.toList());

        if (insertableFavorites.isEmpty()) {
            return Result.error(409, "收藏记录已存在，未插入任何数据");
        }

        int inserted = favoriteMapper.batchInsert(insertableFavorites);
        log.info("请求插入收藏数：{}，实际插入：{}", allFavorites.size(), inserted);

        // 清除涉及用户的缓存
        Set<Long> userIds = insertableFavorites.stream()
                .map(Favorite::getUserId)
                .collect(Collectors.toSet());

        for (Long userId : userIds) {
            String pattern = FAVORITE_CACHE_PREFIX + userId + ":*";
            Set<String> keys = redisTemplate.keys(pattern);
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
            }
        }

        if (inserted == insertableFavorites.size()) {
            return Result.success(true);
        } else {
            return Result.error(500, "部分收藏插入失败");
        }
    }





}
